package net.common.hibernate;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.common.service.ArgumentBean;
import net.common.service.PageBean;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Projections;

public class HibernateHandler {

	protected Session session;

	public HibernateHandler() {
		session = HibernateSessionFactory.getSession();
	}

	public void insert(Object o) {
		session.save(o);
	}

	public void update(Object o) {
		session.update(o);
	}
	
	public void flush() {
		session.flush();
	}

	@SuppressWarnings("rawtypes")
	public Object find(Class clazz, Serializable id) {
		Object obj = session.get(clazz, id);
		return obj;
	}
	
	public void execute(String hql , Map<String, Object> params) {
		Query query = session.createQuery(hql);
		if (params != null) {
			Iterator<String> keys = params.keySet().iterator();
			while (keys.hasNext()) {
				String key = keys.next();
				query.setParameter(key, params.get(key));
			}
		}
		query.executeUpdate();
	}
	
	@SuppressWarnings({"rawtypes" })
	public List executeQuery(String hql , Map<String, Object> params) {
		Query query = session.createQuery(hql);
		if (params != null) {
			Iterator<String> keys = params.keySet().iterator();
			while (keys.hasNext()) {
				String key = keys.next();
				query.setParameter(key, params.get(key));
			}
		}
		return query.list();
	}

	public void delete(Object o) {
		session.delete(o);
	}

	@SuppressWarnings("rawtypes")
	public List splitPage(PageBean pageBean, Class clazz) {
		return this.splitPage(pageBean, null, clazz);
	}

	@SuppressWarnings("rawtypes")
	public List splitPage(PageBean pageBean, List<ArgumentBean> arguments,
			Class clazz) {
		return this.splitPage(pageBean, arguments, null, clazz);
	}

	@SuppressWarnings("rawtypes")
	public List splitPage(PageBean pageBean, List<ArgumentBean> arguments,
			List<Filter> filters, Class clazz) {
		Criteria criteria = session.createCriteria(clazz);
		if (arguments != null) {
			CriteriaHandler.createCriteria(criteria, arguments);
		}
		if (filters != null) {
			for (Filter filter : filters) {
				org.hibernate.Filter f = session.enableFilter(filter
						.getFilterName());
				for (Parmater p : filter.getParmaters()) {
					f.setParameter(p.getName(), p.getValue());
				}
			}
		}
		Long rowCount = (Long) criteria.setProjection(Projections.rowCount())
				.uniqueResult();
		criteria.setFirstResult(pageBean.getStartRow());
		criteria.setMaxResults(pageBean.getCurrentRec());
		pageBean.setTotalRec(rowCount.intValue());
		criteria.setProjection(null);
		return criteria.list();
	}

	@SuppressWarnings("rawtypes")
	public List search(Class clazz) {
		Criteria criteria = session.createCriteria(clazz);
		return criteria.list();
	}

	@SuppressWarnings("rawtypes")
	public List query(StringBuilder hql) {
		return this.query(hql, null, null);
	}

	@SuppressWarnings("rawtypes")
	public List query(StringBuilder hql, PageBean pageBean) {
		return this.query(hql, pageBean, null);
	}
	
	@SuppressWarnings("rawtypes")
	public List query(StringBuilder hql, Map<String, Object> params) {
		return this.query(hql, null, params);
	}

	@SuppressWarnings("rawtypes")
	public List query(StringBuilder hql, PageBean pageBean,
			Map<String, Object> params) {
		if (pageBean != null) {
			total(pageBean, hql, params);
		}
		Query query = session.createQuery(hql.toString());
		if (params != null) {
			Iterator<String> keys = params.keySet().iterator();
			while (keys.hasNext()) {
				String key = keys.next();
				query.setParameter(key, params.get(key));
			}
		}
		if (pageBean != null) {
			query.setFirstResult(pageBean.getStartRow());
			query.setMaxResults(pageBean.getCurrentRec());
		}
		return query.list();
	}

	private void total(PageBean pageBean, StringBuilder hql,
			Map<String, Object> params) {
		Query query = session.createQuery("select count(*) " + hql.toString());
		if (params != null) {
			Iterator<String> keys = params.keySet().iterator();
			while (keys.hasNext()) {
				String key = keys.next();
				query.setParameter(key, params.get(key));
			}
		}
		Long rowCount = (Long) query.uniqueResult();
		pageBean.setTotalRec(rowCount.intValue());
	}

}